#include "common.hpp"
#include "dbuslog.hpp"
#include <thread>
#include <mutex>
std::mutex mtx_test_result;
void DbusArg2Xml(QDomDocument docx,QDomElement &value,const QDBusArgument &v)
{

    bool ok=false;
    if(v.currentType ()== QDBusArgument::BasicType)
    {
        DbusArg2Xml(docx,value,v.asVariant ());

    }else if(v.currentType () ==QDBusArgument::VariantType)
    {
        DbusArg2Xml(docx,value,v.asVariant ());
    }else if(v.currentType () ==QDBusArgument::ArrayType)
    {
        value.setAttribute (METHOD_ARG_TYPE,v.currentType ());
        v.beginArray();
        while (!v.atEnd())
        {
            QDomElement child_arr = docx.createElement (METHOD_ARG_VALUE);
            DbusArg2Xml(docx,child_arr,v.asVariant ());
            value.appendChild (child_arr);
        }
        v.endArray();
    }else if(v.currentType () ==QDBusArgument::StructureType)
    {
        value.setAttribute (METHOD_ARG_TYPE,v.currentType ());
        v.beginStructure ();
        while (!v.atEnd())
        {
            QDomElement child_arr = docx.createElement (METHOD_ARG_VALUE);
            DbusArg2Xml(docx,child_arr,v.asVariant ());
            value.appendChild (child_arr);
        }
        v.endStructure ();
    }else if(v.currentType () ==QDBusArgument::MapType)
    {
        v.beginMap ();
        while (!v.atEnd())
        {
            v.beginMapEntry ();
            v.endMapEntry ();
        }
        v.endMap ();
    }
}

void DbusArg2Xml(QDomDocument docx,QDomElement &value,const QVariant &v)
{

    bool ok=false;
    if(v.type ()== QVariant::Map)
    {
        QVariantMap map = v.toMap ();
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        QStringList keys = map.keys ();
        for(int i=0;i<keys.count ();i++)
        {
            QDomElement child_dict = docx.createElement (METHOD_ARG_DICT);
            QDomElement child_key = docx.createElement (METHOD_ARG_DICT_KEY);
            QDomElement child_value = docx.createElement (METHOD_ARG_VALUE);
            DbusArg2Xml(docx,child_key,keys.at (i));
            DbusArg2Xml(docx,child_value,map[keys.at (i)]);
            child_dict.appendChild (child_key);
            child_dict.appendChild (child_value);
            value.appendChild (child_dict);
        }
    }else if(v.type () == QVariant::List)
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        QVariantList values =v.toList ();
        for(int i=0;i<values.count ();i++)
        {
            QDomElement child_arr = docx.createElement (METHOD_ARG_VALUE);
            DbusArg2Xml(docx,child_arr,values.at (i));
            value.appendChild (child_arr);
        }
    }else if(v.type () == qMetaTypeId<QDBusVariant>())
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        QDomElement child = docx.createElement (METHOD_ARG_VALUE);
        QDBusVariant values =v.value<QDBusVariant>();
        DbusArg2Xml(docx,child,values.variant ());
        value.appendChild (child);
    }else if(v.type () == qMetaTypeId<QDBusArgument>())
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        QDBusArgument values =v.value<QDBusArgument>();
        QDomElement child = docx.createElement (METHOD_ARG_VALUE);
        DbusArg2Xml(docx,child,values.asVariant ());
        value.appendChild (child);
    }else if(v.type () == QMetaType::QByteArray)
    {
        value.setAttribute (METHOD_ARG_TYPE,QMetaType::QByteArray);
        QByteArray d=v.toByteArray ();
        QString str(d.toHex ());
        value.setAttribute (METHOD_ARG_VALUE,str);
    }else
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        if(v.canConvert (QVariant::Int))
        {
            value.setAttribute (METHOD_ARG_VALUE,v.toLongLong ());
        }else if (v.canConvert (QVariant::String)) {
            value.setAttribute (METHOD_ARG_VALUE,v.toString ());
        }
    }
}

void DbusArg2Xml(QDomDocument docx,QDomElement &value,const DVariant &v)
{

    bool ok=false;
    if(v.type ()== DBUS_TYPE_DICT)
    {
        value.setAttribute (METHOD_ARG_TYPE,DBUS_TYPE_DICT);
        dict d=v.getDict (&ok);
        QList<DVariant> keys = d.keys;
        QList<DVariant> values = d.Values;
        for(int i=0;i<keys.count ();i++)
        {
            QDomElement child_dict = docx.createElement (METHOD_ARG_DICT);
            QDomElement child_key = docx.createElement (METHOD_ARG_DICT_KEY);
            QDomElement child_value = docx.createElement (METHOD_ARG_VALUE);
            DbusArg2Xml(docx,child_key,keys.at (i));
            DbusArg2Xml(docx,child_value,values.at (i));
            child_dict.appendChild (child_key);
            child_dict.appendChild (child_value);
            value.appendChild (child_dict);
        }
    }else if(v.type () == DBUS_TYPE_ARRAR)
    {
        value.setAttribute (METHOD_ARG_TYPE,DBUS_TYPE_ARRAR);
        array d=v.getArray(&ok);
        QList<DVariant> values = d.Values;
        for(int i=0;i<values.count ();i++)
        {
            QDomElement child_arr = docx.createElement (METHOD_ARG_VALUE);
            DbusArg2Xml(docx,child_arr,values.at (i));
            value.appendChild (child_arr);
        }
    }else if(v.type () == DBUS_TYPE_STRUCT)
    {
        value.setAttribute (METHOD_ARG_TYPE,DBUS_TYPE_STRUCT);
        structs d=v.getStruct (&ok);
        QList<DVariant> values = d.Values;
        for(int i=0;i<values.count ();i++)
        {
            QDomElement child_arr = docx.createElement (METHOD_ARG_VALUE);
            DbusArg2Xml(docx,child_arr,values.at (i));
            value.appendChild (child_arr);
        }
    }else if(v.type () == QMetaType::QByteArray)
    {
        value.setAttribute (METHOD_ARG_TYPE,QMetaType::QByteArray);
        QByteArray d=v.getByteArray (&ok);
        QString str(d.toHex ());
        value.setAttribute (METHOD_ARG_VALUE,str);
    }else if(v.type () == QMetaType::Char)
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        value.setAttribute (METHOD_ARG_VALUE,v.getInt64 ());
    }else if(v.type () == QMetaType::UShort)
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        value.setAttribute (METHOD_ARG_VALUE,v.getInt64 ());
    }else if(v.type () == QMetaType::UInt)
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        value.setAttribute (METHOD_ARG_VALUE,v.getInt64 ());
    }else if(v.type () == QMetaType::ULongLong)
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        value.setAttribute (METHOD_ARG_VALUE,v.getInt64 ());
    }else if(v.type () == QMetaType::Short)
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        value.setAttribute (METHOD_ARG_VALUE,v.getInt64 ());
    }else if(v.type () == QMetaType::Int)
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        value.setAttribute (METHOD_ARG_VALUE,v.getInt64 ());
    }else if(v.type () == QMetaType::LongLong)
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        value.setAttribute (METHOD_ARG_VALUE,v.getInt64 ());
    }else if(v.type () == QMetaType::QString)
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        value.setAttribute (METHOD_ARG_VALUE,v.getString ());
    }else if(v.type () == qMetaTypeId<QDBusObjectPath>())
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        value.setAttribute (METHOD_ARG_VALUE,v.getString ());
    }else if(v.type () == qMetaTypeId<QDBusSignature>())
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        value.setAttribute (METHOD_ARG_VALUE,v.getString());
    }else if(v.type () == qMetaTypeId<QDBusUnixFileDescriptor>())
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        value.setAttribute (METHOD_ARG_VALUE,v.getInt32 ());
    }else if(v.type () == qMetaTypeId<QDBusVariant>())
    {
        value.setAttribute (METHOD_ARG_TYPE,v.type ());
        QDomElement child = docx.createElement (METHOD_ARG_VALUE);
        DbusArg2Xml(docx,child,v.getVariant ());
        value.appendChild (child);
    }
}


bool Xml2DbusArg(QDomDocument docx,QDomElement &value, DVariant &v)
{
    if(!value.hasAttribute (METHOD_ARG_TYPE))
        return false;
    int vtype = value.attribute (METHOD_ARG_TYPE).toInt ();
    if(vtype == DBUS_TYPE_DICT)
    {
        dict d;
      QDomElement child_dict = value.firstChildElement (METHOD_ARG_DICT);
      while (!child_dict.isNull ()) {
          DVariant key,value;
          QDomElement child_key = child_dict.firstChildElement (METHOD_ARG_DICT_KEY);
          Xml2DbusArg(docx,child_key,key);
          QDomElement child_value = child_dict.firstChildElement (METHOD_ARG_VALUE);
          Xml2DbusArg(docx,child_value,value);
          d.keys.append (key);
          d.Values.append (value);
          child_dict = child_dict.nextSiblingElement (METHOD_ARG_DICT);
      }
      v.setValue (d);
    }else if(vtype == DBUS_TYPE_ARRAR)
    {
        array d;
        QDomElement child = value.firstChildElement (METHOD_ARG_VALUE);
        while (!child.isNull ()) {
            DVariant value;
            Xml2DbusArg(docx,child,value);
            d.Values.append (value);
            child = child.nextSiblingElement (METHOD_ARG_VALUE);
        }
        v.setValue (d);
    }else if(vtype == DBUS_TYPE_STRUCT)
    {
        structs d;
        QDomElement child = value.firstChildElement (METHOD_ARG_VALUE);
        while (!child.isNull ()) {
            DVariant value;
            Xml2DbusArg(docx,child,value);
            d.Values.append (value);
            child = child.nextSiblingElement (METHOD_ARG_VALUE);
        }
        v.setValue (d);
    }else if(vtype == QMetaType::QByteArray)
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            QByteArray arr = QByteArray::fromHex (str.toLatin1 ());
            v.setValue (arr);
            return true;
        }
        return false;
    }else if(vtype == QMetaType::Char)
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            uint8_t value = str.toULongLong ();
            v.setValue (value);
            return true;
        }
        return false;

    }else if(vtype == QMetaType::UShort)
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            uint16_t value = str.toULongLong ();
            v.setValue (value);
            return true;
        }
        return false;
    }else if(vtype == QMetaType::UInt)
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            uint32_t value = str.toULongLong ();
            v.setValue (value);
            return true;
        }
        return false;
    }else if(vtype == QMetaType::ULongLong)
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            uint64_t value = str.toULongLong ();
            v.setValue (value);
            return true;
        }
        return false;
    }else if(vtype == QMetaType::Short)
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            int16_t value = str.toLongLong ();
            v.setValue (value);
            return true;
        }
        return false;
    }else if(vtype == QMetaType::Int)
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            int32_t value = str.toLongLong ();
            v.setValue (value);
            return true;
        }
        return false;
    }else if(vtype == QMetaType::LongLong)
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            int64_t value = str.toLongLong ();
            v.setValue (value);
            return true;
        }
        return false;
    }else if(vtype == QMetaType::QString)
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            v.setValue (str);
            return true;
        }
        return false;
    }else if(vtype == qMetaTypeId<QDBusObjectPath>())
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            v.setValue (QDBusObjectPath(str));
            return true;
        }
        return false;
    }else if(vtype == qMetaTypeId<QDBusSignature>())
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            v.setValue (QDBusSignature(str));
            return true;
        }
        return false;
    }else if(vtype == qMetaTypeId<QDBusUnixFileDescriptor>())
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            v.setValue (QDBusUnixFileDescriptor(str.toInt ()));
            return true;
        }
        return false;
    }else if(v.type () == qMetaTypeId<QDBusVariant>())
    {
        QDomElement child = value.firstChildElement (METHOD_ARG_VALUE);
        if(child.isNull ())
            return false;
        QVariant vchild;
        Xml2DbusArg(docx,child,vchild);
        QDBusVariant dv(vchild);
        v.setValue (dv);
        return true;
    }
    return false;

}

bool Xml2DbusArg(QDomDocument docx,QDomElement &value, QVariant &v)
{
    if(!value.hasAttribute (METHOD_ARG_TYPE))
        return false;
    int vtype = value.attribute (METHOD_ARG_TYPE).toInt ();
    if(vtype == QVariant::Map)
    {
      QVariantMap d;
      QDomElement child_dict = value.firstChildElement (METHOD_ARG_DICT);
      while (!child_dict.isNull ()) {
          QVariant key,value;
          QDomElement child_key = child_dict.firstChildElement (METHOD_ARG_DICT_KEY);
          Xml2DbusArg(docx,child_key,key);
          QDomElement child_value = child_dict.firstChildElement (METHOD_ARG_VALUE);
          Xml2DbusArg(docx,child_value,value);
          d[key.toString ()] = value;
          child_dict = child_dict.nextSiblingElement (METHOD_ARG_DICT);
      }
      v.setValue(d);
      return true;
    }else if(vtype == QVariant::List)
    {
        QVariantList d;
        QDomElement child = value.firstChildElement (METHOD_ARG_VALUE);
        while (!child.isNull ()) {
            QVariant value;
            Xml2DbusArg(docx,child,value);
            d.append (value);
            child = child.nextSiblingElement (METHOD_ARG_VALUE);
        }
        v.setValue (d);
    }else if(vtype == qMetaTypeId<QDBusVariant>())
    {
        QDBusVariant d;
        QVariant vchild;
        QDomElement child = value.firstChildElement(METHOD_ARG_VALUE);
        if(Xml2DbusArg(docx,child,vchild))
        {
            d.setVariant (vchild);
            v.setValue(d);
            return true;
        }
    }else if(vtype == qMetaTypeId<QDBusArgument>())
    {
        QDBusArgument d;
        QVariant vchild;
        QDomElement child = value.firstChildElement(METHOD_ARG_VALUE);
        if(Xml2DbusArg(docx,child,d))
        {
            v.setValue(d);
            return true;
        }
        return false;
    }else if(vtype == QMetaType::QByteArray)
    {
        if(value.hasAttribute (METHOD_ARG_VALUE))
        {
            QString str = value.attribute (METHOD_ARG_VALUE);
            QByteArray arr = QByteArray::fromHex(str.toLatin1 ());
            v.setValue(arr);
            return true;
        }
    }
    else
        {
            if(value.hasAttribute (METHOD_ARG_VALUE))
            {
                QString str = value.attribute (METHOD_ARG_VALUE);
                v.setValue(str);
                return v.convert (vtype);
            }
        }
    return false;
}

bool Xml2DbusArg(QDomDocument docx,QDomElement &value, QDBusArgument &v)
{
    return false;
}



bool structs::operator==(const structs s) const
{
    if(Values.count ()!=s.Values.count ())
        return false;
    for(int i=0;i<Values.count ();i++)
    {
        if(Values.at (i) == s.Values.at (i))
            continue;
        return false;
    }
    return true;
}

bool array::operator==(const array s) const
{
    if(Values.count ()!=s.Values.count ())
        return false;
    for(int i=0;i<Values.count ();i++)
    {
        if(Values.at (i) == s.Values.at (i))
            continue;
        return false;
    }
    return true;
}

bool dict::operator==(const dict s) const
{
    if(keys.count ()!=s.keys.count ())
        return false;
    for(int i=0;i<keys.count ();i++)
    {
        if(keys.at (i) == s.keys.at (i))
            continue;
        return false;
    }
    if(Values.count ()!=s.Values.count ())
        return false;
    for(int i=0;i<Values.count ();i++)
    {
        if(Values.at (i) == s.Values.at (i))
            continue;
        return false;
    }
    return true;
}

DVariant::DVariant()
{
    m_type = QMetaType::UnknownType;
}

QString DVariant::toPlainText()
{
    QString strRet = "";
    bool ok=false;
    int base=10;
     if(m_showModel == ShowModelHex)
     {
        base = 16;
     }
    if(m_type == QMetaType::UnknownType)
    {
        return strRet;
    }else if(m_type == DBUS_TYPE_DICT)
    {
        dict use = this->getDict(&ok);
        if(!ok)
            return strRet;
        if(use.m_Subtypes.count ()<2)
            return strRet;
        strRet +="{";
        int isFrish = true;
        for(int i=0;i<use.Values.count () && i<use.keys.count ();i++) {
            DVariant var0 = use.keys.at (i);
            DVariant var1 = use.Values.at (i);
            if(!isFrish)
            {
                strRet +=",";
            }
            isFrish = false;
            strRet +=var0.toPlainText ();
            strRet +="=";
            strRet +=var1.toPlainText ();
        }
        strRet +="}";
        return strRet;
    }else if(m_type == DBUS_TYPE_ARRAR)
    {
        array use = this->getArray (&ok);
        if(!ok)
            return strRet;

        if(use.m_Subtypes.count ()<1)
            return strRet;
        strRet +="[";
        int isFrish = true;
        foreach (auto var, use.Values) {
            if(!isFrish)
            {
                strRet +=",";
            }
            isFrish = false;
            strRet +=var.toPlainText ();
        }
        strRet +="]";
        return strRet;
    }else if(m_type == DBUS_TYPE_STRUCT)
    {
        structs use = this->getStruct (&ok);
        if(!ok)
            return strRet;
        strRet +="(";
        int isFrish = true;
        foreach (auto var, use.Values) {
            if(!isFrish)
            {
                strRet +=",";
            }
            isFrish = false;
            strRet +=var.toPlainText ();
        }
        strRet +=")";
        return strRet;
    }else if(m_type == QMetaType::QByteArray)
    {
        if(m_showModel == ShowModelHex)
        {
            strRet += QString(m_Values.toByteArray ().toHex (' ')).toUpper ();
        }else
        {
            strRet += "\"";
            QByteArray str = m_Values.toByteArray ();
            str = str.replace ("\r","\\r");
            str = str.replace ("\n","\\n");
            strRet += str;
            strRet += "\"";
        }
        return strRet;
    }else if(m_type == QMetaType::Bool)
    {
        if(m_Values.toBool ())
        {
            strRet += "Ture";
        }else
        {
            strRet += "False";
        }
        return strRet;
    }else if(m_type == QMetaType::UChar)
    {
        strRet += QString::number ((uint8_t)m_Values.toULongLong (),base);
        return strRet;
    }else if(m_type == QMetaType::UShort)
    {
        strRet += QString::number ((uint16_t)m_Values.toULongLong (),base);
        return strRet;
    }else if(m_type == QMetaType::UInt)
    {
        strRet += QString::number ((uint32_t)m_Values.toULongLong (),base);
        return strRet;
    }else if(m_type == QMetaType::ULongLong)
    {
        strRet += QString::number ((uint64_t)m_Values.toULongLong (),base);
        return strRet;
    }else if(m_type == QMetaType::Short)
    {
        strRet += QString::number ((int16_t)m_Values.toLongLong (),base);
        return strRet;
    }else if(m_type == QMetaType::Int)
    {
        strRet += QString::number ((int32_t)m_Values.toLongLong (),base);
        return strRet;
    }else if(m_type == QMetaType::LongLong)
    {
        strRet += QString::number ((int64_t)m_Values.toLongLong (),base);
        return strRet;
    }else if(m_type == QMetaType::Double)
    {
        strRet += m_Values.toString ();
        return strRet;
    }else if(m_type == QMetaType::QString)
    {
        strRet += "\"";
        QString str = m_Values.toString ();
        str = str.replace ("\r","\\r");
        str = str.replace ("\n","\\n");
        strRet += str;
        strRet += "\"";
        return strRet;
    }else if(m_type == qMetaTypeId<QDBusObjectPath>())
    {
        strRet += "\"";
        strRet += m_Values.toString ();
        strRet += "\"";
        return strRet;
    }else if(m_type == qMetaTypeId<QDBusSignature>())
    {
        strRet += "\"";
        strRet += m_Values.toString ();
        strRet += "\"";
        return strRet;
    }else if(m_type == qMetaTypeId<QDBusUnixFileDescriptor>())
    {
        strRet += QString::number ((int32_t)m_Values.toLongLong ());
        return strRet;
    }else if(m_type == qMetaTypeId<QDBusVariant>())
    {
        strRet += "V\"";
        strRet += m_Values.toString ();
        strRet += "\"";
        return strRet;
    }
    return strRet;
}

QString DVariant::toXmlText()
{
    return "";
}


bool DVariant::fromXml(QDomDocument &docx, QDomElement &value)
{
    bool ok=false;
    if(!value.hasAttribute (METHOD_TYPE))
    {
        return false;
    }
    if(!value.hasAttribute (METHOD_ARG_TYPE))
    {
        return false;
    }
    if(value.hasAttribute (METHOD_ARG_SHOW_MODEL))
    {
        m_showModel = (ShowModel)value.attribute (METHOD_ARG_SHOW_MODEL).toInt ();
    }else
    {
        m_showModel = ShowModelDefault;
    }
    m_type = value.attribute (METHOD_TYPE).toInt ();
    m_argTypes = value.attribute (METHOD_ARG_TYPE);
    if(value.hasAttribute (METHOD_ARG_SUB_TYPE))
    {
        QString str = value.attribute (METHOD_ARG_SUB_TYPE);
        QStringList list = str.split (',');
        foreach (QString var, list) {
            m_Subtypes<<var.toInt ();
        }
    }
    if(m_type == QMetaType::UnknownType)
    {
        return false;
    }else if(m_type == DBUS_TYPE_DICT)
    {
        if(m_Subtypes.count ()<2)
            return false;
        dict d;
        d.m_argTypes = m_argTypes;
        d.m_Subtypes = m_Subtypes;
        QDomElement child_dict = value.firstChildElement (METHOD_ARG_DICT);
        while (!child_dict.isNull ()) {
            DVariant key,value;
            QDomElement child_key = child_dict.firstChildElement (METHOD_ARG_DICT_KEY);
            QDomElement child_value = child_dict.firstChildElement (METHOD_ARG_VALUE);
            if(!child_key.isNull () && !child_value.isNull ())
            {
                key.fromXml (docx,child_key);
                value.fromXml (docx,child_value);
                d.keys.append (key);
                d.Values.append (value);
            }
            child_dict = child_dict.nextSiblingElement (METHOD_ARG_DICT);
        }
        setValue (d);
        return true;
    }else if(m_type == DBUS_TYPE_ARRAR)
    {
        if(m_Subtypes.count ()<1)
            return false;
        array d;
        d.m_argTypes = m_argTypes;
        d.m_Subtypes = m_Subtypes;
        QDomElement child_dict = value.firstChildElement (METHOD_ARG_VALUE);
        while (!child_dict.isNull ()) {
            DVariant value;
            value.fromXml (docx,child_dict);
            d.Values.append (value);
            child_dict = child_dict.nextSiblingElement (METHOD_ARG_VALUE);
        }
        setValue (d);
        return true;
    }else if(m_type == DBUS_TYPE_STRUCT)
    {
        structs d;
        d.m_argTypes = m_argTypes;
        d.m_Subtypes = m_Subtypes;
        QDomElement child_dict = value.firstChildElement (METHOD_ARG_VALUE);
        while (!child_dict.isNull ()) {
            DVariant value;
            value.fromXml (docx,child_dict);
            d.Values.append (value);
            child_dict = child_dict.nextSiblingElement (METHOD_ARG_VALUE);
        }
        setValue (d);
        return true;
    }else if(m_type == QMetaType::QByteArray)
    {
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values = QByteArray::fromHex (str.toLatin1 ());
        return true;
    }else if(m_type == QMetaType::Bool)
    {
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        if(str == "True")
        {
            m_Values = QVariant(true);
        }else
        {
             m_Values = QVariant(false);
        }
        return true;
    }else if(m_type == QMetaType::UChar)
    {
        bool ok=false;
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values =str.toULongLong (&ok);
        return ok;
    }else if(m_type == QMetaType::UShort)
    {
        bool ok=false;
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values =str.toULongLong (&ok);
        return ok;
    }else if(m_type == QMetaType::UInt)
    {
        bool ok=false;
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values =str.toULongLong (&ok);
        return ok;
    }else if(m_type == QMetaType::ULongLong)
    {
        bool ok=false;
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values =str.toULongLong (&ok);
        return ok;
    }else if(m_type == QMetaType::Short)
    {
        bool ok=false;
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values =str.toLongLong (&ok);
        return ok;
    }else if(m_type == QMetaType::Int)
    {
        bool ok=false;
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values =str.toLongLong (&ok);
        return ok;
    }else if(m_type == QMetaType::LongLong)
    {
        bool ok=false;
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values =str.toLongLong (&ok);
        return ok;
    }else if(m_type == QMetaType::QString)
    {
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values = str;
        return true;
    }else if(m_type == QMetaType::Double)
    {
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values = str;
        if(!m_Values.canConvert (QMetaType::Double))
        {
            return false;
        }
        return true;
    }else if(m_type == qMetaTypeId<QDBusObjectPath>())
    {
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values = str;
        return true;
    }else if(m_type == qMetaTypeId<QDBusSignature>())
    {
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values = str;
        return true;
    }else if(m_type == qMetaTypeId<QDBusUnixFileDescriptor>())
    {
        bool ok=false;
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values =str.toLongLong (&ok);
        return ok;
    }else if(m_type == qMetaTypeId<QDBusVariant>())
    {
        if(!value.hasAttribute (METHOD_ARG_VALUE))
            return false;
        QString str = value.attribute (METHOD_ARG_VALUE);
        m_Values = str;
        return true;
    }
    return false;
}

bool DVariant::toXml(QDomDocument &docx, QDomElement &value)
{
    bool ok=false;
    value.setAttribute (METHOD_TYPE,QString::number (m_type));
    value.setAttribute (METHOD_ARG_TYPE,m_argTypes);
    value.setAttribute (METHOD_ARG_SHOW_MODEL,m_showModel);
    if(m_Subtypes.count ()>0)
    {
        QStringList str;
        foreach (int var, m_Subtypes) {
            str<<QString::number (var);
        }
        value.setAttribute (METHOD_ARG_SUB_TYPE,str.join (','));
    }
    if(m_type == QMetaType::UnknownType)
    {
        return false;
    }else if(m_type == DBUS_TYPE_DICT)
    {
        dict use = this->getDict(&ok);
        if(!ok)
            return false;
        if(use.m_Subtypes.count ()<2)
            return false;
        value.setAttribute (METHOD_ARG_TYPE,use.m_argTypes);
        QStringList str;
        foreach (int var, use.m_Subtypes) {
            str<<QString::number (var);
        }
        value.setAttribute (METHOD_ARG_SUB_TYPE,str.join (','));
        for(int i=0;i<use.Values.count () && i<use.keys.count ();i++) {
            QDomElement child_dict = docx.createElement(METHOD_ARG_DICT);
            QDomElement item_key =docx.createElement (METHOD_ARG_DICT_KEY);
            QDomElement item_value =docx.createElement (METHOD_ARG_VALUE);
            DVariant var0 = use.keys.at (i);
            var0.toXml (docx,item_key);
            DVariant var1 = use.Values.at (i);
            var1.toXml (docx,item_value);
            child_dict.appendChild (item_key);
            child_dict.appendChild (item_value);
            value.appendChild (child_dict);
        }
        return true;
    }else if(m_type == DBUS_TYPE_ARRAR)
    {
        array use = this->getArray (&ok);
        if(!ok)
            return false;

        if(use.m_Subtypes.count ()<1)
            return false;

        value.setAttribute (METHOD_ARG_TYPE,use.m_argTypes);
        QStringList str;
        foreach (int var, use.m_Subtypes) {
            str<<QString::number (var);
        }
        value.setAttribute (METHOD_ARG_SUB_TYPE,str.join (','));
        foreach (auto var, use.Values) {
            QDomElement sub =docx.createElement (METHOD_ARG_VALUE);
            var.toXml (docx,sub);
            value.appendChild (sub);
        }
        return true;
    }else if(m_type == DBUS_TYPE_STRUCT)
    {
        structs use = this->getStruct (&ok);
        if(!ok)
            return false;
        value.setAttribute (METHOD_ARG_TYPE,use.m_argTypes);
        QStringList str;
        foreach (int var, use.m_Subtypes) {
            str<<QString::number (var);
        }
        value.setAttribute (METHOD_ARG_SUB_TYPE,str.join (','));
        foreach (auto var, use.Values) {
            QDomElement sub =docx.createElement (METHOD_ARG_VALUE);
            var.toXml (docx,sub);
            value.appendChild (sub);
        }
        return true;
    }else if(m_type == QMetaType::QByteArray)
    {
        QString str = QLatin1String(m_Values.toByteArray ().toHex ());
        value.setAttribute (METHOD_ARG_VALUE,str);
        return true;
    }else if(m_type == QMetaType::Bool)
    {
        if(m_Values.toBool ())
        {
            value.setAttribute (METHOD_ARG_VALUE,"True");
        }else
        {
            value.setAttribute (METHOD_ARG_VALUE,"False");
        }
        return true;
    }else if(m_type == QMetaType::UChar)
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toULongLong ());
        return true;
    }else if(m_type == QMetaType::UShort)
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toULongLong ());
        return true;
    }else if(m_type == QMetaType::UInt)
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toULongLong ());
        return true;
    }else if(m_type == QMetaType::ULongLong)
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toULongLong ());
        return true;
    }else if(m_type == QMetaType::Short)
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toLongLong ());
        return true;
    }else if(m_type == QMetaType::Int)
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toLongLong ());
        return true;
    }else if(m_type == QMetaType::LongLong)
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toLongLong ());
        return true;
    }else if(m_type == QMetaType::QString)
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toString ());
        return true;
    }else if(m_type == QMetaType::Double)
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toString ());
        return true;
    }else if(m_type == qMetaTypeId<QDBusObjectPath>())
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toString ());
        return true;
    }else if(m_type == qMetaTypeId<QDBusSignature>())
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toString ());
        return true;
    }else if(m_type == qMetaTypeId<QDBusUnixFileDescriptor>())
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toLongLong ());
        return true;
    }else if(m_type == qMetaTypeId<QDBusVariant>())
    {
        value.setAttribute (METHOD_ARG_VALUE,m_Values.toString ());
        return true;
    }
    return false;
}

bool DVariant::toQDBusArgument(QDBusArgument &dbus_arg)
{
    bool ok=false;
    if(m_type == QMetaType::UnknownType)
    {
        return false;
    }else if(m_type == DBUS_TYPE_DICT)
    {
        dict use = this->getDict(&ok);
        if(!ok)
            return false;
        if(use.m_Subtypes.count ()<2)
            return false;
        dbus_arg.beginMap (use.m_Subtypes.at (0),use.m_Subtypes.at (1));
        for(int i=0;i<use.Values.count () && i<use.keys.count ();i++) {
            DVariant var0 = use.keys.at (i);
            DVariant var1 = use.Values.at (i);
            dbus_arg.beginMapEntry ();
            var0.toQDBusArgument (dbus_arg);
            var1.toQDBusArgument (dbus_arg);
            dbus_arg.endMapEntry ();
        }
        dbus_arg.endStructure ();
        return true;
    }else if(m_type == DBUS_TYPE_ARRAR)
    {
        array use = this->getArray (&ok);
        if(!ok)
            return false;

        if(use.m_Subtypes.count ()<1)
            return false;
        dbus_arg.beginArray (use.m_Subtypes.at (0));
        foreach (auto var, use.Values) {
            var.toQDBusArgument (dbus_arg);
        }
        dbus_arg.endStructure ();
        return true;
    }else if(m_type == DBUS_TYPE_STRUCT)
    {
        structs use = this->getStruct (&ok);
        if(!ok)
            return false;
        dbus_arg.beginStructure ();
        foreach (auto var, use.Values) {
            var.toQDBusArgument (dbus_arg);
        }
        dbus_arg.endStructure ();
        return true;
    }else if(m_type == QMetaType::QByteArray)
    {
        dbus_arg<< m_Values.toByteArray ();
        return true;
    }else if(m_type == QMetaType::Bool)
    {
        dbus_arg<< m_Values.toBool ();
        return true;
    }else if(m_type == QMetaType::UChar)
    {
        if(m_Values.convert (m_type))
        {
            if(m_Values.convert (m_type))
            {
                dbus_arg.appendVariant (m_Values);
            }
        }
        return true;
    }else if(m_type == QMetaType::UShort)
    {
        dbus_arg<< (ushort)m_Values.toUInt ();
        return true;
    }else if(m_type == QMetaType::UInt)
    {
        dbus_arg<< (uint)m_Values.toUInt ();
        return true;
    }else if(m_type == QMetaType::ULongLong)
    {
        dbus_arg<< (qulonglong)m_Values.toULongLong ();
        return true;
    }else if(m_type == QMetaType::Short)
    {
        dbus_arg<< (short)m_Values.toInt ();
        return true;
    }else if(m_type == QMetaType::Double)
    {
        dbus_arg<< (double)m_Values.toDouble ();
        return true;
    }else if(m_type == QMetaType::Int)
    {
        dbus_arg<< (int)m_Values.toInt ();
        return true;
    }else if(m_type == QMetaType::LongLong)
    {
        dbus_arg<< (qlonglong)m_Values.toLongLong ();
        return true;
    }else if(m_type == QMetaType::QString)
    {
        dbus_arg<< m_Values.toString ();
        return true;
    }else if(m_type == qMetaTypeId<QDBusObjectPath>())
    {
        dbus_arg<< QDBusObjectPath(m_Values.toString ());
        return true;
    }else if(m_type == qMetaTypeId<QDBusSignature>())
    {
        dbus_arg<< QDBusSignature(m_Values.toString ());
        return true;
    }else if(m_type == qMetaTypeId<QDBusUnixFileDescriptor>())
    {
        dbus_arg<< QDBusUnixFileDescriptor(m_Values.toInt ());
        return true;
    }else if(m_type == qMetaTypeId<QDBusVariant>())
    {
        dbus_arg<< QDBusVariant(m_Values);
        return true;
    }
    return false;
}

bool DVariant::operator==(const DVariant s) const
{
    bool ok = false;
    if(this->m_type == s.m_type)
    {
        if(m_type == DBUS_TYPE_STRUCT){
            structs d0 = this->getStruct (&ok);
            if(!ok)
            {
                return false;
            }
            structs d1 = s.getStruct (&ok);
            if(!ok)
            {
                return false;
            }
            return d0 == d1;
        }
        else if(m_type == DBUS_TYPE_ARRAR)
        {
            array d0 = this->getArray (&ok);
            if(!ok)
            {
                return false;
            }
            array d1 = s.getArray (&ok);
            if(!ok)
            {
                return false;
            }
            return d0 == d1;
        }else if(m_type == DBUS_TYPE_DICT)
        {
            dict d0 = this->getDict (&ok);
            if(!ok)
            {
                return false;
            }
            dict d1 = s.getDict (&ok);
            if(!ok)
            {
                return false;
            }
            return d0 == d1;
        }
        return getString(&ok)== s.getString();
    }
    return false;
}

void DVariant::setValue(QVariant d){
    m_type = qMetaTypeId<QDBusVariant>();
    m_Values = d;
}



void DVariant::setValue(dict d){
    m_Values.setValue<dict>(d);
    m_type = DBUS_TYPE_DICT;
}

void DVariant::setValue(array d){
    m_Values.setValue<array>(d);
    m_type = DBUS_TYPE_ARRAR;
}

void DVariant::setValue(structs d){
    m_Values.setValue<structs>(d);
    m_type = DBUS_TYPE_STRUCT;
}

void DVariant::setValue(QDBusObjectPath d){
    m_Values = d.path ();
    m_type = qMetaTypeId<QDBusObjectPath>();
}

void DVariant::setValue(QDBusSignature d){
    m_Values = d.signature ();
    m_type = qMetaTypeId<QDBusSignature>();
}

void DVariant::setValue(QDBusUnixFileDescriptor d){
    m_Values = d.fileDescriptor ();
    m_type = qMetaTypeId<QDBusUnixFileDescriptor>();
}

void DVariant::setValue(uint8_t d){
    m_Values.setValue<uint8_t>(d);
    m_type = QMetaType::UChar;
}

void DVariant::setValue(uint16_t d){
    m_Values.setValue<uint16_t>(d);
    m_type = QMetaType::UShort;
}

void DVariant::setValue(int16_t d){
    m_Values.setValue<int16_t>(d);
    m_type = QMetaType::Short;
}

void DVariant::setValue(uint32_t d){
    m_Values.setValue<uint32_t>(d);
    m_type = QMetaType::UInt;
}

void DVariant::setValue(int32_t d){
    m_Values.setValue<int32_t>(d);
    m_type = QMetaType::Int;
}

void DVariant::setValue(uint64_t d){
    m_Values.setValue<uint64_t>(d);
    m_type = QMetaType::ULongLong;
}

void DVariant::setValue(int64_t d){
    m_Values.setValue<int64_t>(d);
    m_type = QMetaType::LongLong;
}

void DVariant::setValue(QByteArray d){
    m_Values.setValue<QByteArray>(d);
    m_type = QVariant::ByteArray;
}

void DVariant::setValue(QDBusVariant d){
    m_Values = d.variant ();
    m_type = qMetaTypeId<QDBusVariant>();
}

QVariant DVariant::getVariant(bool *ok) const
{
    if(type() == qMetaTypeId<QDBusVariant>())
    {
        if(ok)
        {
            *ok=true;
        }
        return m_Values;
    }
    if(ok)
    {
        *ok=false;
    }
    return QVariant();
}

dict DVariant::getDict(bool *ok) const
{
    if(type() == DBUS_TYPE_DICT)
    {
        if(ok)
        {
            *ok=true;
        }
        return m_Values.value<dict>();
    }
    if(ok)
    {
        *ok=false;
    }
    return dict();
}

array DVariant::getArray(bool *ok) const
{
    if(type() == DBUS_TYPE_ARRAR)
    {
        if(ok)
        {
            *ok=true;
        }
        return m_Values.value<array>();
    }
    if(ok)
    {
        *ok=false;
    }
    return array();
}

structs DVariant::getStruct(bool *ok) const
{
    if(type() == DBUS_TYPE_STRUCT)
    {
        if(ok)
        {
            *ok=true;
        }
        return m_Values.value<structs>();
    }
    if(ok)
    {
        *ok=false;
    }
    return structs();
}

uint8_t DVariant::getUInt8(bool *ok) const
{
    return m_Values.toUInt (ok);
}



uint16_t DVariant::getUInt16(bool *ok) const
{
    return m_Values.toUInt (ok);
}

int16_t DVariant::getInt16(bool *ok) const
{
    return m_Values.toInt (ok);
}

uint32_t DVariant::getUInt32(bool *ok) const
{
    return m_Values.toUInt (ok);
}

int32_t DVariant::getInt32(bool *ok) const
{
    return m_Values.toInt (ok);
}

int64_t DVariant::getInt64(bool *ok) const
{
    return m_Values.toLongLong (ok);
}

uint64_t DVariant::getUInt64(bool *ok) const
{
    return m_Values.toULongLong (ok);
}

QString DVariant::getString(bool *ok) const
{
    if(ok)
    {
        *ok=true;
    }
    return m_Values.toString ();
}

QByteArray DVariant::getByteArray(bool *ok) const
{

    if(ok)
    {
        *ok=true;
    }
    return m_Values.toByteArray ();

}

int DVariant::type() const
{
    return m_type;
}

QString DVariant::getArgType() const
{
    bool ok =false;
    if(m_type == DBUS_TYPE_STRUCT){
        QString ret = "(";
        structs d0 = this->getStruct (&ok);
        if(!ok)
        {
            //error;
            return "";
        }
        for (int i=0;i<d0.Values.count ();i++) {
            ret.append (d0.Values.at (i).getArgType ());
        }
        ret +=")";
        return ret;
    }
    else if(m_type == DBUS_TYPE_ARRAR)
    {
        QString ret = "a";
        array d0 = this->getArray (&ok);
        if(d0.Values.count ()==0)
        {
            //error;
            return "";
        }
        ret.append (d0.Values.first ().getArgType ());
        return ret;
    }else if(m_type == DBUS_TYPE_DICT)
    {
        QString ret = "a{";

        dict d0 = this->getDict (&ok);
        if(d0.Values.count ()<2)
        {
            //error;
            return "";
        }
        ret.append (d0.Values.at (0).getArgType ());
        ret.append (d0.Values.at (1).getArgType ());
        ret +="}";
        return ret;
    }else if(m_type == QMetaType::UChar)
    {
        return "y";
    }else if(m_type == QMetaType::Bool)
    {
        return "b";
    }else if(m_type == QMetaType::Short)
    {
        return "n";
    }
    else if(m_type == QMetaType::UShort)
    {
        return "q";
    }
    else if(m_type == QMetaType::LongLong)
    {
        return "x";
    }
    else if(m_type == QMetaType::ULongLong)
    {
        return "t";
    }else if(m_type == QMetaType::Double)
    {
        return "d";
    }else if(m_type == QMetaType::QString)
    {
        return "s";
    }else if(m_type == qMetaTypeId<QDBusObjectPath>())
    {
        return "o";
    }else if(m_type == qMetaTypeId<QDBusSignature>())
    {
        return "g";
    }else if(m_type == qMetaTypeId<QDBusUnixFileDescriptor>())
    {
        return "h";
    }else if(m_type == qMetaTypeId<QDBusVariant>())
    {
        return "v";
    }
    //error;
    return "";
}

QList<int> DVariant::getSubtypes() const
{
    return m_Subtypes;
}

void DVariant::setSubtypes(const QList<int> &Subtypes)
{
    m_Subtypes = Subtypes;
}

QString DVariant::getArgTypes() const
{
    return m_argTypes;
}

void DVariant::setArgTypes(const QString &argTypes)
{
    m_argTypes = argTypes;
}


QString DbusTestModelItem::result() const
{
    QString ret ="";
    if(mtx_test_result.try_lock ())
    {
        ret = m_result;
        mtx_test_result.unlock ();
    }
    return ret;
}

void DbusTestModelItem::setResult(const QString &result)
{
    if(mtx_test_result.try_lock ())
    {
        m_result = result;
        mtx_test_result.unlock ();
    }
}

bool DbusTestModelItem::skip() const
{
    return m_skip;
}

void DbusTestModelItem::setSkip(bool skip)
{
    m_skip = skip;
}
